package com.jdk.demo.nio.bilibili.Maodun.net.qiujuer3.lesson.sample.server;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;

import com.jdk.demo.nio.bilibili.Maodun.net.qiujuer3.lesson.sample.foo.Foo;
import com.jdk.demo.nio.bilibili.Maodun.net.qiujuer3.lesson.sample.foo.constants.TCPConstants;
import com.jdk.demo.nio.bilibili.Maodun.net.qiujuer3.library.clink.core.IoContext;
import com.jdk.demo.nio.bilibili.Maodun.net.qiujuer3.library.clink.impl.IoSelectorProvider;
import com.jdk.demo.nio.bilibili.Maodun.net.qiujuer3.library.clink.impl.SchedulerImpl;

// 注册新连接过程：
// IoSelectorProvider: readSelector = Selector.open()，writeSelector = Selector.open()，startRead()，startWrite()
// tcpServer.start()
// TCPServer：listener.start()监听OP_ACCEPT
// TCPServer：当有客户端连接上来后，构建ClientHandler(socketChannel, TCPServer.this);
// ClientHandler：connector.setup(socketChannel)
// Connector：生成SocketChannelAdapter(channel, context.getIoProvider(), this)，准备读取数据readNextMessage()
// readNextMessage(): 调用异步接收数据receiver.receiveAsync(echoReceiveListener);
// SocketChannelAdapter.readNextMessage(): 调用ioProvider.registerInput(channel, inputCallback)，往ioProvider上注册OP_READ
// IoSelectorProvider.registerInput(): registerSelection(channel, readSelector, SelectionKey.OP_READ, inRegInput, inputCallbackMap, callback)，注册得到sk，并把sk和inputCallback放入map

// 接收客户端写入事件过程：
// IoSelectorProvider.startRead(): 当sk可读后，调用handleSelection(selectionKey, SelectionKey.OP_READ, inputCallbackMap, inputHandlePool)
// IoSelectorProvider.handleSelection(): 通过sk获取到回调inputCallback，放入线程池进行调度
// IoProvider$HandleInputCallback: canProviderInput()，这个方法在SocketChannelAdapter的inputCallback()里重写了
// SocketChannelAdapter$inputCallback: 读取客户端数据，如果读取到数据，调用echoReceiveListener.onCompleted(args)
// echoReceiveListener.onCompleted(args): 打印数据，读取下一条数据readNextMessage()
public class Server {
    public static void main(String[] args) throws IOException {
    	File cachePath = Foo.getCacheDir("server");
        IoContext.setup()
                .ioProvider(new IoSelectorProvider())
                .scheduler(new SchedulerImpl(1))
                .start();

        TCPServer tcpServer = new TCPServer(TCPConstants.PORT_SERVER, cachePath);
        boolean isSucceed = tcpServer.start();
        if (!isSucceed) {
            System.out.println("Start TCP server failed!");
            return;
        }

        UDPProvider.start(TCPConstants.PORT_SERVER);

        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
        String str;
        do {
            str = bufferedReader.readLine();
            if(str == null || Foo.COMMAND_EXIT.equalsIgnoreCase(str)){
            	break;
            }
            if(str.length() == 0) {
            	continue;
            }
            // 发送字符串
            tcpServer.broadcast(str);
        } while (true);

        UDPProvider.stop();
        tcpServer.stop();

        IoContext.close();
    }
}
